package com.ruoyi.system.service.impl;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.SysArticleCategory;
import com.ruoyi.system.domain.dto.DashboardItemDto;
import com.ruoyi.system.domain.vo.DashboardTrendResp;
import com.ruoyi.system.domain.vo.DashboardTypeResp;
import com.ruoyi.system.domain.vo.SysArticleReq;
import com.ruoyi.system.domain.vo.SysArticleResp;
import com.ruoyi.system.enums.LikeRecordEnum;
import com.ruoyi.system.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.SysArticleMapper;
import com.ruoyi.system.domain.SysArticle;

/**
 * 文章Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-05-02
 */
@Service
public class SysArticleServiceImpl implements ISysArticleService 
{
    @Autowired
    private SysArticleMapper sysArticleMapper;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private ISysLikeRecordService likeRecordService;
    @Autowired
    private ISysCollectService collectService;

    /**
     * 查询文章
     * 
     * @param id 文章主键
     * @return 文章
     */
    @Override
    public SysArticleResp selectSysArticleById(Long id)
    {
        SysArticle sysArticle = sysArticleMapper.selectSysArticleById(id);
        SysArticleResp resp = BeanUtil.copyProperties(sysArticle, SysArticleResp.class);
        SysUser sysUser = userService.selectUserById(sysArticle.getUserId());
        resp.setNickName(sysUser.getNickName());
        resp.setAvatar(sysUser.getAvatar());
        resp.setLikeNum(likeRecordService.selectSysLikeRecordByTargetIdAndType(id, LikeRecordEnum.ARTICLE.getKey()));
        resp.setCollectNum(collectService.selectSysCollectByArticleId(sysArticle.getId()));
        addViewsNum(sysArticle);
        return resp;
    }

    private void addViewsNum(SysArticle sysArticle) {
        sysArticle.setViewsNum(sysArticle.getViewsNum() + 1);
        sysArticleMapper.updateSysArticle(sysArticle);
    }

    /**
     * 查询文章列表
     * 
     * @param sysArticle 文章
     * @return 文章
     */
    @Override
    public List<SysArticleResp> selectSysArticleList(SysArticleReq sysArticle)
    {
        if (Objects.nonNull(sysArticle.getIsSelf()) && sysArticle.getIsSelf()) {
            sysArticle.setUserId(SecurityUtils.getUserId());
        }
        return sysArticleMapper.selectSysArticleList(sysArticle)
                .stream().map(item -> {
                    SysArticleResp resp = BeanUtil.copyProperties(item, SysArticleResp.class);
                    SysUser sysUser = userService.selectUserById(item.getUserId());
                    resp.setNickName(sysUser.getNickName());
                    resp.setAvatar(sysUser.getAvatar());
                    resp.setLikeNum(likeRecordService.selectSysLikeRecordByTargetIdAndType(item.getId(), LikeRecordEnum.ARTICLE.getKey()));
                    resp.setCollectNum(collectService.selectSysCollectByArticleId(item.getId()));
                    return resp;
                }).collect(Collectors.toList());
    }

    /**
     * 新增文章
     * 
     * @param sysArticle 文章
     * @return 结果
     */
    @Override
    public int insertSysArticle(SysArticle sysArticle)
    {
        sysArticle.setUserId(SecurityUtils.getUserId());
        sysArticle.setViewsNum(0);
        sysArticle.setCreateTime(DateUtils.getNowDate());
        return sysArticleMapper.insertSysArticle(sysArticle);
    }

    /**
     * 修改文章
     * 
     * @param sysArticle 文章
     * @return 结果
     */
    @Override
    public int updateSysArticle(SysArticle sysArticle)
    {
        sysArticle.setUpdateTime(DateUtils.getNowDate());
        return sysArticleMapper.updateSysArticle(sysArticle);
    }

    /**
     * 批量删除文章
     * 
     * @param ids 需要删除的文章主键
     * @return 结果
     */
    @Override
    public int deleteSysArticleByIds(Long[] ids)
    {
        return sysArticleMapper.deleteSysArticleByIds(ids);
    }

    /**
     * 删除文章信息
     * 
     * @param id 文章主键
     * @return 结果
     */
    @Override
    public int deleteSysArticleById(Long id)
    {
        return sysArticleMapper.deleteSysArticleById(id);
    }

    @Override
    public Integer selectCount() {
        return sysArticleMapper.selectCount();
    }

    @Override
    public DashboardTrendResp selectTrendList() {
        List<Date> dates = new ArrayList<>();
        // 去掉时分秒
        Date date =  DateUtil.beginOfDay(new Date());
        int days = 7;
        for(int i = 0; i < days; i++) {
            dates.add(DateUtil.offsetDay(date, -1 * i));
        }

        Map<Date, Integer> groupDateMap = sysArticleMapper.getCountGroupByDate(dates)
                .stream()
                .map(item -> new DashboardItemDto(DateUtil.beginOfDay(item.getDate()), item.getCount()))
                .collect(Collectors.toMap(DashboardItemDto::getDate, DashboardItemDto::getCount));

        List<String> xData = new ArrayList<>();
        List<Integer> yData = new ArrayList<>();
        dates.forEach(item -> {
            xData.add(DateUtil.formatDate(item));
            yData.add(groupDateMap.getOrDefault(item, 0));
        });

        return new DashboardTrendResp(xData, yData);
    }

    @Override
    public List<DashboardTypeResp> selectTypeList() {
        Map<Long, List<SysArticle>> articleMaps = sysArticleMapper.selectSysArticleList(new SysArticle()).stream().collect(Collectors.groupingBy(SysArticle::getCategoryId));
        Map<Long, String> categoryMap = SpringUtil.getBean(ISysArticleCategoryService.class).selectSysArticleCategoryList(new SysArticleCategory()).stream()
                .collect(Collectors.toMap(SysArticleCategory::getId, SysArticleCategory::getName));
        return articleMaps.keySet().stream().map(item -> {
            DashboardTypeResp res = new DashboardTypeResp();
            res.setName(categoryMap.get(item));
            res.setValue(articleMaps.get(item).size());
            return res;
        }).collect(Collectors.toList());
    }
}
